# TODO: Add comment
# 
# Author: rogb
###############################################################################


setClass("BasicDateData",
		representation=list(
				Date="Date",
				Data="matrix"
		),contains=c("BasicInstrument")
)

BasicDateData <- function(Currency,Name,Date,Data){
	new("BasicDateData",Currency=Currency,Name=Name,Date=Date,Data=as.matrix(Data))
}

# o1 <- BasicDateData(c("EUR","CHF"),c("Peter","Roger"),Sys.Date()+0:1,cbind(c(100,200),c(300,400)))

setMethod("show","BasicDateData",function(object){
			tmp <- object@Data
			rownames(tmp) <- as.character(getDate(object))
			colnames(tmp) <- info(object)
			print(tmp)
		})

setMethod("dim","BasicDateData",function(x){
			dim(x@Data)
		})

getDate <- function(object){
			object@Date
		}

getDate.character <- function(object){
			as.character(object@Date)
		}

"setDate<-" <- function(object,value){
			object@Date <- value
			object
		}

getData <- function(object){
			object@Data
		}

"setData<-" <- function(object,value){
			object@Data <- value
			object
		}

setMethod("dimnames",signature=c("BasicDateData"),function(x){
			list(Currency=x@Currency,Name=x@Name,Date=x@Date)
		})

setReplaceMethod("dimnames",signature=c("BasicDateData"),function(x,value){
			x@Currency <- value$Currency
			x@Name <- value$Name
			x@Date <- value$Date
			x
		})

# o1 <- BasicDateData(c("EUR","CHF"),c("Peter","Roger"),Sys.Date()+1:0,cbind(c(100,200),c(300,400)))
# i <- Sys.Date()+0:5
# j <- 1
# drop = FALSE
# x <- o1
# o1[i,j,drop=T]

setMethod("[",signature=c("BasicDateData","missing","numeric"),function(x,i,j,drop){
			Result <- x
			Result@Currency <- x@Currency[j]
			Result@Name <- x@Name[j]
			Result@Data <- as.matrix(x@Data[,j])
			Result
		})

setMethod("[",signature=c("BasicDateData","Date","missing"),function(x,i,j,drop){
			Result <- x
			if(drop==TRUE){
				iValidDate <- i[is.element(i,x@Date)]
				iValid <- as.character(iValidDate)
				row.names(x@Data) <- as.character(x@Date)
				Result@Date <- iValidDate
				Result@Data <- as.matrix(x@Data[iValid,,drop=FALSE])
			}else{
				Date <- i
				Data <- matrix(0,nrow=length(i),ncol=length(x))
				iValid <- as.character(i[is.element(i,x@Date)])
				row.names(x@Data) <- as.character(x@Date)
				row.names(Data) <- as.character(i)
				Data[iValid,] <- x@Data[iValid,,drop=FALSE]
				Result@Date <- i
				Result@Data <- as.matrix(Data)
			}
			Result
		})

setMethod("[",signature=c("BasicDateData","Date","numeric"),function(x,i,j,drop){
			tmp <- x[i,,drop=drop]
			Result <- tmp[,j,drop=drop]
			Result
		})

setMethod("[",signature=c("BasicDateData","numeric","missing"),function(x,i,j,drop){
			Result <- x
			Result@Date <- x@Date[i]
			Result@Data <- x@Data[i,,drop=FALSE]
			Result
		})

setMethod("[",signature=c("BasicDateData","numeric","numeric"),function(x,i,j,drop){
			tmp <- x[i,,drop=drop]
			Result <- tmp[,j,drop=drop]
			Result
		})

# x <- BasicDateData(c("EUR","CHF"),c("Peter","Roger"),Sys.Date()+1:0,cbind(c(100,200),c(300,400)))
# j <- "CHF"
# drop = FALSE
# x <- o1
# o1[i,j,drop=T]

setMethod("[",signature=c("BasicDateData","missing","character"),function(x,i,j,drop){
			Result <- x
			idx <- is.element(x@Currency,j)
			Result@Currency <- x@Currency[idx]
			Result@Name <- x@Name[idx]
			Result@Data <- x@Data[,idx,drop=FALSE]
			Result
		})

# i <- Sys.Date()
# j <- "EUR"

setMethod("[",signature=c("BasicDateData","Date","character"),function(x,i,j,drop){
			tmp <- x[i,,drop=drop]
			Result <- tmp[,j,drop=drop]
			Result
		})


setMethod("+",signature=c("BasicDateData","numeric"),function(e1,e2){
			e1@Data <- e1@Data + e2
			e1
		})
setMethod("+",signature=c("numeric","BasicDateData"),function(e1,e2){
			e2 + e1
		})

setMethod("-",signature=c("BasicDateData","numeric"),function(e1,e2){
			e1@Data <- e1@Data - e2
			e1
		})
setMethod("-",signature=c("numeric","BasicDateData"),function(e1,e2){
			e2 - e1
		})

setMethod("*",signature=c("BasicDateData","numeric"),function(e1,e2){
			e1@Data <- e1@Data * e2
			e1
		})
setMethod("*",signature=c("numeric","BasicDateData"),function(e1,e2){
			e2 * e1
		})

setMethod("/",signature=c("BasicDateData","numeric"),function(e1,e2){
			e1@Data <- e1@Data / e2
			e1
		})
setMethod("/",signature=c("numeric","BasicDateData"),function(e1,e2){
			e2 / e1
		})

# b1 <- BasicDateData("CHF","Rogers CashFlow",Sys.Date()+(0:100)*100,rnorm(101))
# b2 <- BasicDateData(Currency="CHF","Test",Date=Sys.Date()+(10:110)*100,Data=rnorm(101))
# b3 <- BasicDateData("EUR",character(1),Sys.Date()+(20:120)*100,rnorm(101))
# b4 <- BasicDateData("CHF","A1",Sys.Date()+(30:130)*100,rnorm(101))
# dotdotdot <- c(b3,b4)
# x <- b1
# y <- b2
# class(merge(b1,b2,b3,b4))

setMethod("merge",signature=c("BasicDateData","BasicDateData"),function(x, y,...){
			Result <- y
			dotdotdot <- c(...)
			classX <- class(x)
			classY <- class(y)
			
			if(any(classX!=c(classY,sapply(dotdotdot,class)))){
				stop("merge: arguments not of same class")
			}
			
			nDot <- length(dotdotdot)
			if(nDot>0){
				y <- merge(y,dotdotdot[[1]],dotdotdot[-1])
			}
			
			Date <- sort(unique(c(x@Date,y@Date)))
			Currency <- c(x@Currency,y@Currency)
			Name <- character(length(Currency)) 
			Name[1:length(x@Currency)] <- x@Name
			Name[(length(x@Currency)+1):length(Currency)] <- y@Name
			Data <- cbind(x[Date,,drop=FALSE]@Data,y[Date,,drop=FALSE]@Data)
			
			Result@Currency <- Currency
			Result@Name <- Name
			Result@Date <- Date
			Result@Data <- Data
			Result
		})


